package com.stylefeng.guns.modular.system.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.enums.SqlLike;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.stylefeng.guns.core.base.controller.BaseController;
import com.stylefeng.guns.core.base.tips.ErrorTip;
import com.stylefeng.guns.core.cache.CacheKit;
import com.stylefeng.guns.core.common.Tools.CodeMsg;
import com.stylefeng.guns.core.common.Tools.Result;
import com.stylefeng.guns.core.common.annotion.BussinessLog;
import com.stylefeng.guns.core.common.constant.Const;
import com.stylefeng.guns.core.common.constant.dictmap.UserDict;
import com.stylefeng.guns.core.common.constant.state.ManagerStatus;
import com.stylefeng.guns.core.common.exception.BizExceptionEnum;
import com.stylefeng.guns.core.exception.GunsException;
import com.stylefeng.guns.core.log.LogObjectHolder;
import com.stylefeng.guns.core.shiro.ShiroKit;
import com.stylefeng.guns.core.shiro.ShiroUser;
import com.stylefeng.guns.core.util.ToolUtil;
import com.stylefeng.guns.core.validater.Update;
import com.stylefeng.guns.modular.system.model.Org;
import com.stylefeng.guns.modular.system.model.UserCw;
import com.stylefeng.guns.modular.system.service.IOrgService;
import com.stylefeng.guns.modular.system.service.IUserCwService;
import com.stylefeng.guns.modular.system.warpper.UserCwWarpper;
import io.swagger.annotations.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 系统用户表& #40;成为智能& #41;控制器
 *
 * @author zhangyalin
 * @Date 2018-08-24 10:33:17
 */
@RestController
@RequestMapping(value = {"/gunsApi/auth/userCw"})
@Api(value="用户操作controller",tags={"用户操作接口"})
public class UserCwController extends BaseController {

    private String PREFIX = "/system/userCw/";

    @Autowired
    private IUserCwService userCwService;
    
    @Autowired
    private IOrgService orgService;
    
    private static final String CACHE_STRATEGY = "local";

    /**
     * 跳转到系统用户表& #40;成为智能& #41;首页
     */
    @RequestMapping("")
    public String index() {
        return PREFIX + "userCw.html";
    }

    /**
     * 跳转到添加系统用户表& #40;成为智能& #41;
     */
    @RequestMapping("/userCw_add")
    public String userCwAdd() {
        return PREFIX + "userCw_add.html";
    }

    /**
     * 跳转到修改系统用户表& #40;成为智能& #41;
     */
    @RequestMapping("/userCw_update/{userCwId}")
    public String userCwUpdate(@PathVariable("userCwId") Integer userCwId, Model model) {
        UserCw userCw = userCwService.selectById(userCwId);
        model.addAttribute("item",userCw);
        LogObjectHolder.me().set(userCw);
        return PREFIX + "userCw_edit.html";
    }

    /**
     * 获取系统用户表& #40;成为智能& #41;列表
     */
    @ApiOperation(value="获取系统用户列表",notes = "获取系统用户列表",httpMethod ="GET")
    @GetMapping(value = "/list")
    @CachePut(value=CACHE_STRATEGY,key = "'userCwList_'+#soId+'-'+#spId+'-'+#suState")
   public Result list(@ApiParam(name = "condition", value = "系统用户名或登录名, 支持模糊查询", required = false) @RequestParam(value="condition",required = false)  String condition,
                      @ApiParam(name = "soId", value = "机构编号", required = false) @RequestParam(value="soId",required = false)  Integer soId,
                      @ApiParam(name = "spId", value = "岗位编号", required = false) @RequestParam(value="spId",required = false)  Integer spId,
                      @ApiParam(name = "suState", value = "状态", required = false) @RequestParam(value="suState",required = false)  Integer suState,
                      @ApiParam(name = "pageNum", value = "当前页数", required = false) @RequestParam(value = "pageNum", defaultValue = "1",required = false) Integer pageNum,
                      @ApiParam(name = "pageSize", value = "每页显示条数", required = false) @RequestParam(value = "pageSize", defaultValue = "10000",required = false) Integer pageSize
    ) {
        Page<UserCw> page = new Page<>(pageNum,pageSize);
        Wrapper<UserCw> wrapper = new EntityWrapper<>();
        if(ToolUtil.isNotEmpty(suState)){
            wrapper.eq("su_state",suState);
        }else{
            wrapper.ne("su_state",ManagerStatus.DELETED.getCode());
        }
        
        String token=this.getHttpServletRequest().getHeader("Authorization").substring(7);
        ShiroUser shiroUser= CacheKit.get(CACHE_STRATEGY, token);
        if (shiroUser==null){
            return Result.error(CodeMsg.TOKEN_VRRIFY_ERROR);
        }else{
            String accout = shiroUser.getAccount();
            if (StringUtils.isNotEmpty(accout) && !StringUtils.equalsIgnoreCase("admin", accout)) {
                int soId_ = shiroUser.getSoId();
                if (ToolUtil.isNotEmpty(soId_)) {
                    Wrapper<Org> orgWrapper = new EntityWrapper<>();
                    orgWrapper.eq("so_id", soId_).or();
                    orgWrapper.like("so_pids", "%[" + soId_ + "]%");
                    List<Org> list = this.orgService.selectList(orgWrapper);
                if (list != null && list.size() > 0) {
                    List<Integer> soIdList = list.parallelStream().map(Org::getSoId).collect(Collectors.toList());
                if (soIdList != null && soIdList.size() > 0) {
                    wrapper.in("so_id", soIdList);
            }
          }
        }
      }

      if (ToolUtil.isNotEmpty(condition)) {
        wrapper.andNew();
        wrapper.like("sui_name", condition).or();
        wrapper.like("su_login_name", condition).or();
        wrapper.like("su_phone", condition);
      }
      if (ToolUtil.isNotEmpty(soId)) {
        wrapper.andNew();
        wrapper.eq("so_id", soId);
      }
      if (ToolUtil.isNotEmpty(spId)) {
        wrapper.and();
        wrapper.eq("sp_id", spId).or();
        wrapper.like("sup_id", spId + "", SqlLike.DEFAULT);
      }
      page = this.userCwService.selectPage(page, wrapper);
      List<UserCw> list = page.getRecords();
      List<Map<String, Object>> mList = new ArrayList<>();
      for (UserCw o : list) {
        Map map = BeanUtil.beanToMap(o);
        mList.add(map);
      }
      super.warpObject(new UserCwWarpper(mList));
      BeanUtil.setFieldValue(page, "records", mList);
      return Result.success(page);
}
    }

    /**
     * 新增系统用户表& #40;成为智能& #41;
     */
    @ApiOperation(value="新增用户",notes = "新增用户",httpMethod ="POST")
    @PostMapping(value = "/add",produces="application/json",consumes = "application/json")
    @CachePut(value=CACHE_STRATEGY,key="'userCw_'+#userCw.getSuId()")
     public Result add(@Valid @RequestBody @ApiParam(name = "userCw", value = "新增用户实体", required = true)  UserCw userCw) {
        // 完善账号信息
        // 判断账号是否重复
        UserCw newU =new UserCw();
        newU.setSuLoginName(userCw.getSuPhone());
        newU.setSuEmail(userCw.getSuEmail());
        UserCw theUser = userCwService.selectOne(new EntityWrapper<>(newU));
        if(theUser!=null){
            return Result.error(CodeMsg.USER_ALREADY_REG);
        }
        userCw.setSuLoginName(userCw.getSuPhone());
        userCw.setSuSalt(ShiroKit.getRandomSalt(5));
        //添加用户  默认手机号后六位
        userCw.setSuLoginPwd(ShiroKit.md5(StringUtils.substring(StringUtils.trimToNull(userCw.getSuPhone()),-6), userCw.getSuSalt()));
        userCw.setSuState(ManagerStatus.OK.getCode());
        Boolean b=false;
        try{
             b=this.userCwService.insert(userCw);
             }catch(Exception e){
            throw  new GunsException(BizExceptionEnum.USER_INSERT_DUPLICATE);
        }
        if (b)
            return Result.success(CodeMsg.USER_INSERT_SUCESS);
        else
            return Result.error(CodeMsg.USER_INSERT_ERROR);
    }

    /**
     * 删除系统用户(成为智能);
     */
    @ApiOperation(value="删除用户",notes = "删除用户",httpMethod ="DELETE")
    @DeleteMapping(value = "/delete")
    @CacheEvict(value =CACHE_STRATEGY,key = "'userCw_'+#userCwId")//这是清除缓存
    public Result delete(@ApiParam(name = "userCwId",type="String", value = "登录账户唯一编号", required = true) @RequestParam("userCwId") String userCwId) {
        if (ToolUtil.isEmpty(userCwId)) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //不能删除超级管理员
        if (userCwId.equals(Const.ADMIN_ID)) {
            throw new GunsException(BizExceptionEnum.CANT_DELETE_ADMIN);
        }
        UserCw userCw=this.userCwService.selectById(userCwId);
        if(userCw!=null){
            userCw.setSoId(null);
            userCw.setSpId(null);
            userCw.setSrId(null);
            userCw.setSuState(ManagerStatus.DELETED.getCode());
        }else{
            throw new GunsException(BizExceptionEnum.USER_NOT_EXISTED);
        }
    
        userCw.updateById();
        return Result.success();
    }

    /**
     * 修改系统用户表& #40;成为智能& #41;
     */
    @ApiOperation(value="修改用户",notes = "修改用户",httpMethod ="POST")
    @PostMapping(value = "/update")
    @CachePut(value = CACHE_STRATEGY,key = "'userCw_'+#userCw.getSuId()")//更新用户数据
    public Result update(@ApiParam(name = "userCw", value = "修改用户实体", required = true) @RequestBody  @Validated(value = Update.class) UserCw userCw, BindingResult result) {
        if (result.hasErrors()) {
            throw new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //完善pids,根据pid拿到pid的pids
        ShiroUser shiroUser=this.getShiroUser();
        Integer userId=shiroUser.getId();
        UserCw user=null;
        if(userId!=null){
            user=this.userCwService.selectById(userId);
        }
            UserCw oldUser = userCwService.selectById(userCw.getSuId());
            //忽略空值 忽略suLoginPwd suSalt
            BeanUtil.copyProperties(userCw,oldUser, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true).setIgnoreProperties("suLoginPwd","suSalt").setFieldMapping(getUserCwMappingMap()));
            this.userCwService.updateById(oldUser);
       
        return Result.success();
    }

    /***
     * 手机号填充登录名
     * @return 映射map
     */
    private static Map<String, String> getUserCwMappingMap() {
        Map<String, String> map = new HashMap<String, String>() {
            {
                put("suPhone", "suLoginName");//司机手机号
            }
        };
        return map;
    }

    /**
     * 系统用户表& #40;成为智能& #41;详情
     */
    @ApiOperation(value="查看用户明细",notes = "获取用户明细信息",httpMethod ="GET")
    @ApiImplicitParam(name = "userCwId", value = "查看用户明细", dataType = "String")
    @GetMapping(value = "/detail")
    public Result detail(@ApiParam(name = "userCwId", value = "账户唯一编号",type = "String") @RequestParam(value = "userCwId",required = false) Integer userCwId) {
       if(userCwId==null){
           ShiroUser shiroUser=this.getShiroUser();
           userCwId=shiroUser.getId();
       }
        UserCw userCw = userCwService.selectById(userCwId);
        List<Map<String, Object>> mList=new ArrayList<>();
        Map map= BeanUtil.beanToMap(userCw);
        mList.add(map);
        return Result.success(super.warpObject(new UserCwWarpper(mList)));
    }
    
    /**
     * 修改密码
     */
    @ApiOperation(value="修改密码",notes = "修改密码",httpMethod ="GET")
    @GetMapping(value="/modify")
    @BussinessLog(value = "修改密码")
    @CacheEvict(value=CACHE_STRATEGY,allEntries = true)
   public Object modify(@ApiParam(name = "oldPwd", value = "原密码",type = "String", required = true) @RequestParam("oldPwd") String oldPwd,
                      @ApiParam(name = "newPwd", value = "新密码",type = "String", required = true) @RequestParam("newPwd") String newPwd
                      ) {
        if (ToolUtil.isOneEmpty(oldPwd,newPwd)) {
            throw new GunsException(BizExceptionEnum.PWD_EXISTS_ERROR);
        }
        //完善pids,根据pid拿到pid的pids
        ShiroUser shiroUser=this.getShiroUser();
        Integer userId=shiroUser.getId();
        UserCw userCw=null;
        if(userId!=null){
            userCw=this.userCwService.selectById(userId);
        }
        String salt=userCw.getSuSalt();
        
        if (StringUtils.isBlank(salt)){
            salt=ShiroKit.getRandomSalt(5);
        }
        String old=userCw.getSuLoginPwd();
        String o=ShiroKit.md5(oldPwd, salt);
        String n=ShiroKit.md5(newPwd, salt);
        if(!StringUtils.equals(old,o)){
            return new GunsException(BizExceptionEnum.OLD_PWD_NOT_RIGHT);
        }
        
        if (StringUtils.equals(o,n)){
            return new GunsException(BizExceptionEnum.NEW_OLD_PWD_MATCH);
        }
        userCw.setSuSalt(salt);
        userCw.setSuLoginPwd(n);
        userCw.updateById();
        return SUCCESS_TIP;
    }
    
    
    /**
     * 重置密码
     */
    @ApiOperation(value="重置密码",notes = "重置密码",httpMethod ="GET")
    @ApiImplicitParam(name = "userId", value = "重置密码", required = true, dataType = "String")
    @GetMapping(value="/reset")
    @BussinessLog(value = "重置密码", key = "userId", dict = UserDict.class)
    @CacheEvict(value=CACHE_STRATEGY,key="'userCw_'+#userId")
    public Object reset(@ApiParam(name = "userId", value = "账户唯一编号",type = "String", required = true) @RequestParam("userId") String userId) {
        if (ToolUtil.isEmpty(userId)) {
            return new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        UserCw userCw= this.userCwService.selectById(userId);
        if(userCw!=null){
            userCw.setSuLoginPwd(ShiroKit.md5(StringUtils.substring(StringUtils.trimToNull(userCw.getSuPhone()),-6), userCw.getSuSalt()));
            userCw.updateById();
            return SUCCESS_TIP;
        }
        return new ErrorTip(400,"用户不存在！");

    }

    /**
     * 分配角色
     */
    @ApiOperation(value="分配角色",notes = "分配角色",httpMethod ="GET")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "对象ID", required = true, dataType = "String"),
            @ApiImplicitParam(name = "roleIds", value = "角色ID集", required = true, dataType = "String")
    })
    @GetMapping(value="/setRole")
    @BussinessLog(value = "分配角色", key = "userId,roleIds", dict = UserDict.class)
    @CachePut(value=CACHE_STRATEGY,key="'userCw_'+#userId")
    public Object setRole(@ApiParam(name = "userId", value = "账户唯一编号",type = "String", required = true) @RequestParam("userId") Integer userId, @RequestParam("roleIds") String roleIds) {
        if (ToolUtil.isEmpty(userId)) {
            return Result.error(new ErrorTip(500, "用户ID不能为空！"));
        }
        UserCw userCw = this.userCwService.selectById(userId);
        if(userCw==null){
            return new GunsException(BizExceptionEnum.NO_THIS_USER);
        }
        //不能修改超级管理员
        if (userId.equals(Const.ADMIN_ID)) {
            return new GunsException(BizExceptionEnum.CANT_CHANGE_ADMIN);
        }
        this.userCwService.setRoles(userId, roleIds);
        return SUCCESS_TIP;
    }

    /**
     * 冻结用户
     */
    @ApiOperation(value="冻结用户",notes = "冻结用户",httpMethod ="GET")
    @ApiImplicitParam(name = "userId", value = "对象ID", required = true, dataType = "Integer")
    @GetMapping(value="/freeze")
    @BussinessLog(value = "冻结用户")
    @CacheEvict(value = CACHE_STRATEGY,key = "'userCw_'+#userId")//更新缓存
    public Object freeze(@RequestParam("userId") Integer userId) {
        if (ToolUtil.isEmpty(userId)) {
            return new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        //不能冻结超级管理员
        if (userId.equals(Const.ADMIN_ID)) {
            return new GunsException(BizExceptionEnum.CANT_FREEZE_ADMIN);
        }
        assertAuth(userId);
        this.userCwService.setStatus(userId, ManagerStatus.FREEZED.getCode());
        return SUCCESS_TIP;
    }


    /**
     * 解除冻结用户
     */
    @ApiOperation(value="解除冻结用户",notes = "解除冻结用户",httpMethod ="GET")
    @ApiImplicitParam(name = "userId", value = "对象ID", required = true, dataType = "String")
    @GetMapping(value="/unfreeze")
    @BussinessLog(value = "解除冻结用户")
    @CachePut(value = CACHE_STRATEGY,key = "'userCw_'+#userId")//更新缓存
    public Object unfreeze(@RequestParam("userId") Integer userId) {
        if (ToolUtil.isEmpty(userId)) {
            return new GunsException(BizExceptionEnum.REQUEST_NULL);
        }
        assertAuth(userId);
        this.userCwService.setStatus(userId, ManagerStatus.OK.getCode());
        return SUCCESS_TIP;
    }


    /**
     * 判断当前登录的用户是否有操作这个用户的权限
     */
    private void assertAuth(Integer userCwId) {
        List<Integer> deptDataScope = ShiroKit.getDeptDataScope();
        UserCw userCw = this.userCwService.selectById(userCwId);
        Integer soId = userCw.getSoId();
        if (deptDataScope.contains(soId)) {
            return;
        } else {
            throw new GunsException(BizExceptionEnum.NO_PERMITION);
        }

    }
    @Cacheable(value=CACHE_STRATEGY,key = "'userCw_'+#result.getId()")
    public  ShiroUser getShiroUser(){
        String token= getHttpServletRequest().getHeader("Authorization").substring(7);
        return CacheKit.get(CACHE_STRATEGY,token);
    }
}
